package com.zbkj.crmeb.order.oprocess;


import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.zbkj.crmeb.chant.request.PurchaseProductRequest;
import com.zbkj.crmeb.enums.RoleEnum;
import com.zbkj.crmeb.enums.SwitchEnum;
import com.zbkj.crmeb.front.response.*;
import com.zbkj.crmeb.merchant.api.request.BuyMemberRequest;
import com.zbkj.crmeb.payment.vo.wechat.AttachVo;
import com.zbkj.crmeb.payment.vo.wechat.PayParamsVo;
import com.zbkj.crmeb.payment.wechat.WeChatPayService;
import com.zbkj.crmeb.store.model.*;
import com.zbkj.crmeb.store.service.*;
import com.zbkj.crmeb.user.service.UserMemberRecordService;
import com.zbkj.crmeb.wechat.service.WeChatService;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.crmeb.core.exception.CrmebException;
import com.zbkj.crmeb.agent.model.AgentAccount;
import com.zbkj.crmeb.agent.service.AgentAccountFlowService;
import com.zbkj.crmeb.agent.service.AgentAccountService;
import com.zbkj.crmeb.agent.service.AgentFreezeBillService;
import com.zbkj.crmeb.bill.service.MerFreezeBillService;
import com.zbkj.crmeb.chant.model.ChannelMerchantAccount;
import com.zbkj.crmeb.chant.service.IChannelMerchantAccountService;
import com.zbkj.crmeb.enums.AccountFlowTypeEnum;
import com.zbkj.crmeb.enums.OrderTradeTypeEnum;
import com.zbkj.crmeb.finance.request.FundsMonitorSearchRequest;
import com.zbkj.crmeb.front.request.OrderCreateRequest;
import com.zbkj.crmeb.front.request.OrderPayRequest;
import com.zbkj.crmeb.marketing.service.StoreCouponUserService;
import com.zbkj.crmeb.payment.service.OrderPayService;
import com.zbkj.crmeb.payment.vo.wechat.CreateOrderResponseVo;
import com.zbkj.crmeb.store.request.StoreAccountInfoRequest;
import com.zbkj.crmeb.store.request.StoreOrderRefundRequest;
import com.zbkj.crmeb.store.response.StoreCartResponse;
import com.zbkj.crmeb.store.utilService.OrderUtils;
import com.zbkj.crmeb.system.service.SystemAdminService;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.model.UserBill;
import com.zbkj.crmeb.user.request.UserOperateFundsRequest;
import com.zbkj.crmeb.user.service.UserBillService;
import com.zbkj.crmeb.user.service.UserService;

import lombok.extern.slf4j.Slf4j;


/**
 * @Description: 觅蓝订单
 */
@Service("stroreOrderProcess")
@Slf4j
public class StroreOrderProcess extends AbstractPayOrderProcess {

    public static final Logger logger = LoggerFactory.getLogger(StroreOrderProcess.class);

    @Autowired
    private UserService userService;
    @Autowired
    private OrderUtils orderUtils;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private StoreOrderRefundService storeOrderRefundService;
    @Autowired
    private UserBillService userBillService;
    @Autowired
    private StoreOrderStatusService storeOrderStatusService;
    @Autowired
    private StoreAccountInfoService storeAccountInfoService;
    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;
    @Autowired
    private SystemAdminService systemAdminService;
    @Autowired
    private UserCommissionService userCommissionService;
    @Autowired
    private AccountFlowService accountFlowService;
    @Autowired
    private IChannelMerchantAccountService channelMerchantAccountService;
    @Autowired
    private StoreOrderInfoService storeOrderInfoService;
    @Autowired
    private MerFreezeBillService merFreezeBillService;
    @Autowired
    StoreCouponUserService storeCouponUserService;
    @Autowired
    AgentAccountService agentAccountService;
    @Autowired
    AgentFreezeBillService agentFreezeBillService;
    @Autowired
    AgentAccountFlowService agentAccountFlowService;
    @Lazy
    @Autowired
    private WeChatPayService weChatPayService;
    @Autowired
    private WeChatService weChatService;
    @Autowired
    private UserMemberRecordService userMemberRecordService;
    @Autowired
    private StoreOrderRefundApplyService storeOrderRefundApplyService;
    @Value("${productType.merchantId}")
    private Integer productTypeMerchantId;

    @Override
    public OrderPayResponse creatOrder(String orderKey, OrderCreateRequest request, String ip) {
        OrderPayResponse orderPayResponse = new OrderPayResponse();
        User currentUser = userService.getInfo();
        // 检查订单是否存在
        if(orderUtils.checkOrderExist(orderKey, currentUser.getUid())){
            throw new CrmebException(orderKey + "订单已存在");
        }

        // 检测支付方式
        if(!orderUtils.checkPayType(request.getPayType())){
            throw new CrmebException("暂不支持该支付方式，请刷新页面或者联系管理员");
        }

        String existCacheOrder = orderUtils.cacheGetOrderInfo(userService.getUserIdException(), orderKey);
        if(null == existCacheOrder) throw new CrmebException("订单已过期,请刷新当前页面!");
        ConfirmOrderResponse cor = JSONObject.parseObject(existCacheOrder, ConfirmOrderResponse.class);

        // 订单计算与缓存处理
        ComputeOrderResponse computeOrderResponse = orderUtils.computedOrder(request, cor, orderKey);
        if(SwitchEnum.OPEN.getCode().equals(computeOrderResponse.getIsAllowSelfPickUp())){
            request.setIsAllowSelfPickUp(SwitchEnum.OPEN.getCode());
        }
        if (cor.getPriceGroup().getPayPrice().compareTo(new BigDecimal("5000")) > 0 && cor.getAddressInfo().getAreaType() != null && cor.getAddressInfo().getAreaType() == 1  ) {
            orderPayResponse.setStatus("PRICE_OVER_5000");
            orderPayResponse.setMessage("您购买的商品为跨境商品，根据海关规定跨境商品不能超过5000元，请您重新选择购买数量!");
            return orderPayResponse;
        }
        // 检查订单状态生成订单
        StoreOrder orderCreated = orderUtils.createOrder(request, cor, request.getIsChannel(), request.getStoreId(), orderKey);
        if(null == orderCreated) {
        	throw new CrmebException("订单生成失败");
        }

        // 发货地是否是中国 不是大陆发货就是跨境商品，跨境商品不使用积分:大陆发货才使用积分
        List<StoreCartResponse> cartResponseList = cor.getCartInfo().stream().filter(storeCartResponse -> !Objects.equals(storeCartResponse.getProductInfo().getTempId(), 1)).collect(Collectors.toList());

        boolean existForeign = false;
        if(CollectionUtils.isNotEmpty(cartResponseList)){
            existForeign = true;
        }
        // 立即购买支付
        if(request.getIsNew()){
            HashMap<String, Object> resultMap = new HashMap<>();
            OrderPayRequest orderPayRequest = new OrderPayRequest();
            orderPayRequest.setFrom(request.getFrom());
            orderPayRequest.setPaytype(request.getPayType());
            orderPayRequest.setUni(orderCreated.getOrderId());
            // 组装返回前端识别值
            doPayOrder(orderPayRequest, ip, resultMap, orderCreated, existForeign);
            OrderPayItemResponse itemResponse = new OrderPayItemResponse();
            String payType = null;
            switch (request.getPayType()){
                case Constants.PAY_TYPE_WE_CHAT:
                case Constants.PAY_TYPE_WE_CHAT_FROM_PROGRAM:
                    payType = "微信支付下单成功 请支付";
                    orderPayResponse.setStatus("WECHAT_PAY");
                    orderPayResponse.setJsConfig(resultMap.get("jsConfig"));
                    break;
                case Constants.PAY_TYPE_WE_CHAT_FROM_NATIVE:
                	payType = "微信扫码支付下单成功 请支付";
                	orderPayResponse.setStatus("WECHAT_NATIVE_PAY");
                	orderPayResponse.setJsConfig(resultMap.get("jsConfig"));
                	break;
                case Constants.PAY_TYPE_YUE:
                    payType = "余额支付成功";
                    orderPayResponse.setStatus("SUCCESS");
                    break;
                case Constants.PAY_TYPE_OFFLINE:
                    payType = "线下支付";
                    orderPayResponse.setStatus("SUCCESS");
                    break;
            }
            orderPayResponse.setMessage(payType);
            itemResponse.setKey(orderCreated.getOrderId());
            itemResponse.setOrderId(orderKey);
            orderPayResponse.setResult(itemResponse);
            System.out.println("---------------------" + orderCreated.getOrderId() + "==" + orderKey);
        }else{
            String tempStatus = "";
            switch (request.getPayType()){
                case Constants.PAY_TYPE_WE_CHAT:tempStatus="WECHAT_H5_PAY";  break;
                case Constants.PAY_TYPE_WE_CHAT_NATIVE:tempStatus="WECHAT_NATIVE_PAY";  break;
                case Constants.PAY_TYPE_YUE:tempStatus="SUCCESS";  break;
                case Constants.PAY_TYPE_OFFLINE:tempStatus="SUCCESS";  break;
            }
            orderPayResponse.setStatus(tempStatus);
            OrderPayItemResponse itemResponse = new OrderPayItemResponse();
            itemResponse.setKey(orderCreated.getOrderId());
            itemResponse.setOrderId(orderKey);
            orderPayResponse.setResult(itemResponse);
            System.out.println("---------------------" + orderCreated.getOrderId() + "==" + orderKey);
        }


        return orderPayResponse;
    }

    /**
     * 仅仅支付
     * 订单支付完之后给出状态值 以便前端使用， 后期这里也可以抽出对象
     * ORDEREEXIST, EXTENDORDER, PAYERROR, SUCCESS, WECHATPAY, PAYDEFICIENCY, WECHATH5PAY
     * @param request
     * @param ip
     * @param resultMap
     * @param existStoreOrder
     * @return
     */
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public boolean doPayOrder(OrderPayRequest request, String ip, HashMap<String, Object> resultMap, StoreOrder existStoreOrder, boolean existForeign) {
        StoreOrder storeOrder = storeOrderService.getById(existStoreOrder.getId());
        // 无需实际付款
        if (storeOrder.getPayPrice().compareTo(BigDecimal.ZERO)==0){
            OrderPayResponse orderPayResponseY = new OrderPayResponse("SUCCESS", new OrderPayItemResponse(request.getUni(), existStoreOrder.getOrderId()));
            resultMap.put("result", orderPayResponseY.getResult());
            resultMap.put("jsConfig", null);
            resultMap.put("status","SUCCESS");
            //更新积分放在afterPaySuccess里
            orderPayService.afterPaySuccess(storeOrder);
            return true;
        }
        // 无需实际付款
        if (storeOrder.getPayPrice().compareTo(new BigDecimal("5000")) > 0){
            OrderPayResponse orderPayResponseY = new OrderPayResponse("NONE", new OrderPayItemResponse(request.getUni(), existStoreOrder.getOrderId()));
            resultMap.put("result", orderPayResponseY.getResult());
            resultMap.put("jsConfig", null);
            resultMap.put("status","SUCCESS");
            return false;
        }
        if(Constants.PAY_TYPE_YUE.equals(request.getPaytype()) && existForeign){
            throw new CrmebException("存在跨境商品，不能使用余额支付！");
        }
        existStoreOrder.setPayType(request.getPaytype());
        CreateOrderResponseVo orderPayResult = orderPayService.payOrder(existStoreOrder.getId(), request.getFrom(), ip);
        // 下面组装前端所需数据
        switch (existStoreOrder.getPayType()){
            case Constants.PAY_TYPE_WE_CHAT:
            case Constants.PAY_TYPE_WE_CHAT_NATIVE:
            case Constants.PAY_TYPE_WE_CHAT_FROM_PROGRAM:
                if(existStoreOrder.getPayType().equals(Constants.PAY_TYPE_WE_CHAT_FROM_H5)){
                    OrderPayItemResponse itemResponse = new OrderPayItemResponse(orderPayResult.getPrepayId(), existStoreOrder.getOrderId());
                    OrderPayResponse orderPayResponse = new OrderPayResponse("WECHAT_H5_PAY",itemResponse);
                    resultMap.put("result", orderPayResponse.getResult());
                    resultMap.put("status","WECHAT_H5_PAY");
                    resultMap.put("jsConfig", orderPayResult.getTransJsConfig());
                    log.info("--------------- 使用WECHAT_H5_PAY支付订单 ---------------");
                    return true;
                } else if(existStoreOrder.getPayType().equals(Constants.PAY_TYPE_WE_CHAT_FROM_NATIVE)) {
                    OrderPayItemResponse itemResponse = new OrderPayItemResponse(orderPayResult.getPrepayId(), existStoreOrder.getOrderId());
                    OrderPayResponse orderPayResponse = new OrderPayResponse("WECHAT_NATIVE_PAY", itemResponse);
                    resultMap.put("result", orderPayResponse.getResult());
                    resultMap.put("status","WECHAT_NATIVE_PAY");
                    resultMap.put("jsConfig", orderPayResult.getTransJsConfig());
                    log.info("--------------- 使用WECHAT_NATIVE_PAY支付订单 ---------------");
                    return true;
                } else {
                    OrderPayItemResponse itemResponse = new OrderPayItemResponse(orderPayResult.getPrepayId(), existStoreOrder.getOrderId());
                    OrderPayResponse orderPayResponse = new OrderPayResponse("WECHAT_PAY",itemResponse);
                    resultMap.put("result", orderPayResponse.getResult());
                    resultMap.put("status","WECHAT_PAY");
                    resultMap.put("jsConfig", orderPayResult.getTransJsConfig());
                    log.info("--------------- 使用WECHAT_PAY支付订单 ---------------");
                    return true;
                }
            case Constants.PAY_TYPE_YUE:
                OrderPayResponse orderPayResponseY = new OrderPayResponse("SUCCESS", new OrderPayItemResponse(request.getUni(), existStoreOrder.getOrderId()));
                resultMap.put("result", orderPayResponseY.getResult());
                resultMap.put("status","SUCCESS");
                log.info("--------------- 使用YUE支付订单 ---------------");
//                }
                return true;
            case Constants.PAY_TYPE_OFFLINE:
                log.info("--------------- 使用PAY_TYPE_OFFLINE支付订单 ---------------");
                resultMap.put("result", new OrderPayItemResponse(request.getUni(), existStoreOrder.getOrderId()));
                resultMap.put("status","SUCCESS");
                return true;
        }
        return false;
    }

    @Override
    public void callBack(StoreOrder order) {

    }

    @Override
    public boolean refund(StoreOrderRefundRequest request) {
        try{
            StoreOrderInfo storeOrderInfo = storeOrderInfoService.getById(request.getOrderId());
            if(null == storeOrderInfo){
                throw new CrmebException("未查到订单");
            }
            StoreOrder storeOrder = storeOrderService.getById(storeOrderInfo.getOrderId());
            storeOrderInfo.setActivityGroupId(storeOrder.getActivityId());
            if(!storeOrder.getPaid()){
                throw new CrmebException("未支付无法退款");
            }
            StoreAccountInfoRequest storeAccountInfoRequest = new StoreAccountInfoRequest();
            storeAccountInfoRequest.setOrderId(storeOrderInfo.getChildOrderNumber());
            storeAccountInfoRequest.setUid(storeOrder.getUid());
            storeAccountInfoRequest.setTradeType(OrderTradeTypeEnum.REFUND.getType());
            BigDecimal refundMoney = storeAccountInfoService.selectAlreadyRefundPrice(storeAccountInfoRequest);
            //解析storeOrderInfo
            StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
            StoreProductAttrValue attrInfo = storeCartResponse.getProductInfo().getAttrInfo();
            if(request.getAmount().compareTo(attrInfo.getPaidPrice()) > 0){
                throw new CrmebException("退款金额大于支付金额，请修改退款金额");
            }
            if(request.getAmount().compareTo(BigDecimal.ZERO) == 0 && request.getType() == 2){
            	throw new CrmebException("补偿性退款金额需大于零");
            }
            if(request.getAmount().add(refundMoney).compareTo(attrInfo.getPaidPrice()) > 0){
                throw new CrmebException("已补偿性退款共计"+refundMoney+"元,请修改退款金额");
            }
            //用户
            User user = userService.getById(storeOrder.getUid());
            Boolean refunded = false;
            //退款
            switch (storeOrder.getPayType()){
                case Constants.PAY_TYPE_WE_CHAT:
                case Constants.PAY_TYPE_WE_CHAT_NATIVE:
                    refunded = storeOrderRefundService.refund(request, storeOrder);
                    break;
                case Constants.PAY_TYPE_YUE:
                    UserOperateFundsRequest userOperateFundsRequest = new UserOperateFundsRequest();
                    userOperateFundsRequest.setUid(storeOrder.getUid());
                    userOperateFundsRequest.setValue(request.getAmount());
                    userOperateFundsRequest.setFoundsCategory(Constants.USER_BILL_CATEGORY_MONEY);
                    userOperateFundsRequest.setFoundsType(Constants.ORDER_STATUS_REFUNDED);
                    userOperateFundsRequest.setType(1);
                    userOperateFundsRequest.setTitle(Constants.ORDER_STATUS_STR_REFUNDED);
                    boolean addMoney = userService.updateFounds(userOperateFundsRequest, false); //更新余额
                    if(!addMoney){
                        throw new CrmebException("余额退款失败");
                    }
                    //新增日志
                    boolean addBill = userBillService.saveRefundBill(request, user);
                    if(!addBill){
                        throw new CrmebException("余额退款失败");
                    }
                    break;
                case Constants.PAY_TYPE_OFFLINE:
                    break;
                default:
                    throw new CrmebException("支付方式异常");
            }

            if(!refunded && Constants.PAY_TYPE_WE_CHAT.equals(storeOrder.getPayType())){
                return false;
            }
            //修改订单退款状态
            if(request.getType() == 1){
                //查询申请记录
                StoreOrderRefundApply refundApply = storeOrderRefundApplyService.getOne(Wrappers.<StoreOrderRefundApply>lambdaQuery().eq(StoreOrderRefundApply::getInfoId, storeOrderInfo.getId()).orderByDesc(StoreOrderRefundApply::getId).last("LIMIT 1"));
                if(refundApply != null && refundApply.getProcessType() == null){
                    refundApply.setProcessType(1);
                    refundApply.setProcessTime(new Date());
                    refundApply.setRefundPrice(request.getAmount());
                    storeOrderRefundApplyService.updateById(refundApply);
                }
                storeOrderInfo.setRefundStatus(2);
                storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_REFUNDED);
                storeOrderInfo.setRefundPrice(request.getAmount());
            }else if(request.getType() == 2){
                storeOrderInfo.setRefundStatus(3);
                //补偿性退款 返回订单状态待发货
//                storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_NOT_SHIPPED);
                storeOrderInfo.setRefundPrice(request.getAmount().add(storeOrderInfo.getRefundPrice()));
            }else{
                throw new CrmebException("选择退款状态错误");
            }
//            boolean updateOrder = storeOrderService.updateByEntity(storeOrder);
            boolean b = storeOrderInfoService.updateById(storeOrderInfo);
            if(!b){
                storeOrderStatusService.saveRefund(storeOrderInfo.getOrderId(),storeOrderInfo.getChildOrderNumber(),request.getAmount(), "失败",storeOrderInfo.getRefundStatus() == 2);
                throw new CrmebException("订单更新失败");
            }else {
                if(request.getType() == 1){
                    orderUtils.updateOrderStatus(storeOrderInfo.getOrderId());
                }
            }
            //TODO 发送模板消息, 异步
            Boolean payType = orderUtils.getPayType(storeOrder.getPayType());
            //退款成功
            storeOrderStatusService.saveRefund(storeOrderInfo.getOrderId(),storeOrderInfo.getChildOrderNumber(), request.getAmount(), null,storeOrderInfo.getRefundStatus() == 2);
            //佣金
            //subtractBill(request, Constants.USER_BILL_CATEGORY_MONEY, Constants.USER_BILL_TYPE_BROKERAGE, Constants.USER_BILL_CATEGORY_BROKERAGE_PRICE);
            //新增退款佣金
            if(storeOrderInfo.getStatus().equals(Constants.ORDER_STATUS_H5_REFUNDED)){
                userCommissionService.refundCommission(storeOrderInfo);
            }

            //新增账户明细
            addAccountInfo(storeOrder,storeOrderInfo,request.getAmount());
            //商户信息
            ChannelMerchantAccount merchantAccount = new ChannelMerchantAccount().setMerId(storeOrder.getMerId());
            //根据订单号判断订单来源 --外部订单退款到可用余额(退货退款)
            if(storeOrder.getOrderId().contains("OT")){
                //外部订单,退款到商户可用余额
                merchantAccount.setAccount(attrInfo.getPaidPrice());
                channelMerchantAccountService.calcMoney(merchantAccount);
                log.info("外部订单退款,商户可用余额增加,商户:{},金额:{}",storeOrder.getMerId(), attrInfo.getPaidPrice());
                accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                        AccountFlowTypeEnum.PRODUCT,attrInfo.getPaidPrice(),null,null,"第三方订单退款");
            }else {
                //退款,商户冻结余额减少
                if(storeOrderInfo.getRefundStatus() == 2){
                    if(!Objects.equals(storeOrderInfo.getIsEurope(),1)){
                        BigDecimal firstAgentFrozen = BigDecimal.ZERO,
                                secondAgentFrozen = BigDecimal.ZERO;
                        //服务商
                        if(attrInfo.getSecondAgentCost() != null && attrInfo.getFirstAgentCost() != null){
                            //二级利润
                            secondAgentFrozen = attrInfo.getCost().subtract(attrInfo.getSecondAgentCost());
                            //一级利润
                            firstAgentFrozen = attrInfo.getSecondAgentCost().subtract(attrInfo.getFirstAgentCost());
                        }else if(attrInfo.getSecondAgentCost() == null && attrInfo.getFirstAgentCost() != null){
                            //一级利润
                            firstAgentFrozen = attrInfo.getCost().subtract(attrInfo.getFirstAgentCost());
                        }
                        if(attrInfo.getFirstAgentId() != null){
                            updateAgentFrozen(storeOrderInfo, attrInfo.getFirstAgentId(), firstAgentFrozen);
                        }
                        if(attrInfo.getSecondAgentId() != null){
                            updateAgentFrozen(storeOrderInfo, attrInfo.getSecondAgentId(), secondAgentFrozen);
                        }
                    }
                    boolean autoFlag = Objects.equals(storeOrderInfo.getIsEurope(),1) || Objects.equals(storeOrderInfo.getAutonomous(),1);
                    if(payType == null){
                        //自主发货
                        BigDecimal increaseAccount = autoFlag ? null : attrInfo.getCost().add(attrInfo.getTaxAndSecondPrice());
                        merchantAccount.setFreezeAccount(BigDecimal.ZERO)
                                .setAccount(increaseAccount);
                        channelMerchantAccountService.calcMoney(merchantAccount);
                        log.info("用户退货退款,减少商户微信收款余额，商户:{},金额:{}",storeOrder.getMerId(),request.getAmount());
                        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                AccountFlowTypeEnum.PRODUCT,increaseAccount,null,BigDecimal.ZERO,"订单退款");
                    }else if(payType){
                        //盈利金额
                        BigDecimal profit = autoFlag ?  attrInfo.getPrice() : attrInfo.getPaidPrice().subtract(attrInfo.getCost()).subtract(attrInfo.getTaxAndSecondPrice());
                        if(profit.compareTo(BigDecimal.ZERO)<0){
                            BigDecimal price = profit.negate().add(attrInfo.getPaidPrice().subtract(request.getAmount()));
                            merchantAccount.setAccount(price);
                            channelMerchantAccountService.calcMoney(merchantAccount);
                            log.info("用户退货退款,增加商户商户可用金额，商户:{},金额:{}",storeOrder.getMerId(),price);
                            accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                    AccountFlowTypeEnum.PRODUCT,price,null,null,"订单退款");
                        }else {
                            BigDecimal price = profit.subtract(attrInfo.getPaidPrice().subtract(request.getAmount()));
                            //修改冻结账单
                            merFreezeBillService.updateAmountFrozen(storeOrderInfo,price);
                            log.info("用户退货退款,减少商户商户冻结金额，商户:{},金额:{}",storeOrder.getMerId(),price);
                            merchantAccount.setFreezeAccount(price.negate());
                            channelMerchantAccountService.calcMoney(merchantAccount);
                            //记录商户流水操作  冻结金额
                            accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                    AccountFlowTypeEnum.PRODUCT,null,null,price.negate(),"订单退款");
                        }
                    }else {
                        BigDecimal increaseAccount = autoFlag ? null : attrInfo.getCost().add(attrInfo.getTaxAndSecondPrice());
                        merchantAccount.setWithdrawAccount(request.getAmount().negate())
                                .setAccount(increaseAccount);
                        channelMerchantAccountService.calcMoney(merchantAccount);
                        log.info("用户退货退款,减少商户微信收款余额，商户:{},金额:{}",storeOrder.getMerId(),request.getAmount());
                        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                AccountFlowTypeEnum.PRODUCT,increaseAccount,request.getAmount().negate(),null,"订单退款");
                    }
                    //返还优惠券,商户金额
                    buckleCoupon(storeOrder,storeOrderInfo);
                    //退积分,退商户金额  --扣除子订单积分
                    buckleIntegral(storeOrder,storeOrderInfo,Constants.USER_BILL_CATEGORY_INTEGRAL, Constants.USER_BILL_TYPE_DEDUCTION, Constants.USER_BILL_TYPE_PAY_PRODUCT_INTEGRAL_BACK,request.getType());
                }else {
                    if(payType == null){
                        merchantAccount.setAccount(BigDecimal.ZERO);
                        channelMerchantAccountService.calcMoney(merchantAccount);
                        log.info("补偿性退款,减少商户商户可用余额，商户:{},金额:{}",storeOrder.getMerId(),BigDecimal.ZERO);
                        //记录商户流水操作
                        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                AccountFlowTypeEnum.PRODUCT,BigDecimal.ZERO,null,null,"补偿性退款");
                    }else if(payType){
                        //补偿性退款
                        merchantAccount.setAccount(request.getAmount().negate());
                        channelMerchantAccountService.calcMoney(merchantAccount);
                        log.info("补偿性退款,减少商户商户可用余额，商户:{},金额:{}",storeOrder.getMerId(),request.getAmount());
                        //记录商户流水操作
                        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                AccountFlowTypeEnum.PRODUCT,request.getAmount().negate(),null,null,"补偿性退款");
                    }else {
                        //补偿性退款
                        merchantAccount.setWithdrawAccount(request.getAmount().negate());
                        channelMerchantAccountService.calcMoney(merchantAccount);
                        log.info("补偿性退款,减少商户微信收款余额，商户:{},金额:{}",storeOrder.getMerId(),request.getAmount());
                        //记录商户流水操作
                        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                AccountFlowTypeEnum.PRODUCT,null,request.getAmount().negate(),null,"补偿性退款");
                    }
                }
            }
            //退货增加库存
            if(request.getType() == 1){
                //自主发货不加库存
                if(!Objects.equals(storeOrderInfo.getAutonomous(),1)){
                    storeProductAttrValueService.addProductValueStock(storeOrderInfo);
                }
            }
            return true;
        }catch (Exception e){
            throw new CrmebException(e.getMessage());
        }
    }

    public void updateAgentFrozen(StoreOrderInfo storeOrderInfo, Integer agentId, BigDecimal firstAgentFrozen) {
        AgentAccount agentAccount = new AgentAccount();
        agentAccount.setAgentId(agentId)
                .setFreezeAccount(firstAgentFrozen.negate());
        agentAccountService.calcMoney(agentAccount);
        log.info("用户退货退款,减少服务商冻结金额，服务商:{},金额:{}",agentId,firstAgentFrozen);
        agentAccountFlowService.saveAccountFlow(agentId,storeOrderInfo.getOrderId(),null,null,
                AccountFlowTypeEnum.PRODUCT,null,firstAgentFrozen.negate(),"订单退款");
        agentFreezeBillService.updateAmountFrozen(storeOrderInfo,firstAgentFrozen);
    }

    private void buckleCoupon(StoreOrder storeOrder, StoreOrderInfo storeOrderInfo){
        if(storeOrder.getCouponPrice().compareTo(BigDecimal.ZERO) < 1 || storeOrderInfo.getCouponPrice().compareTo(BigDecimal.ZERO) < 1){
            return;
        }
//        ChannelMerchantAccount entity = new ChannelMerchantAccount();
//        entity.setMerId(storeOrder.getMerId());
//        entity.setAccount(storeOrderInfo.getCouponPrice());
//        channelMerchantAccountService.calcMoney(entity);
//        //商户流水记录
//        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
//                AccountFlowTypeEnum.PRODUCT,storeOrderInfo.getCouponPrice(),null,null,"客户退款时优惠券返还");
        int count = storeOrderInfoService.count(Wrappers.lambdaQuery(StoreOrderInfo.class).gt(StoreOrderInfo::getCouponPrice, BigDecimal.ZERO)
                .ne(StoreOrderInfo::getStatus, -2).eq(StoreOrderInfo::getOrderId, storeOrderInfo.getOrderId()));
        if(count < 1){
            //返还优惠券
            storeCouponUserService.rollbackByCancelOrder(storeOrder);
        }
    }

    private void addAccountInfo(StoreOrder storeOrder, StoreOrderInfo storeOrderInfo,BigDecimal refundPrice){
        User user = userService.getById(storeOrder.getUid());
        StoreAccountInfo info = new StoreAccountInfo();
        info.setOrderId(storeOrderInfo.getChildOrderNumber());
        info.setUid(storeOrder.getUid());
        if(null!=user){
            info.setRealName(user.getNickname());
            info.setNowMoney(user.getNowMoney());
        }
        info.setTradeType(OrderTradeTypeEnum.REFUND.getType());
        info.setTradePrice(refundPrice);
        info.setPayType(storeOrder.getPayType());
        if(Constants.PAY_TYPE_WE_CHAT.equals(storeOrder.getPayType())){
            info.setIsAccount(0);
        }
        info.setRemark("商品退款"+refundPrice);
        if (Objects.nonNull(storeOrder.getActivityGroupId())){
            // TODO 拼团活动系统自动退款，暂时写死
            info.setOperateId(0);
        } else {
            info.setOperateId(systemAdminService.getAdminId());
        }
        storeAccountInfoService.save(info);
    }

    @Override
    public HashMap<String, Object> toPayOrder(OrderPayRequest request, String ip) {
        HashMap<String, Object> resultMap = new HashMap<>();
        User currentUser = userService.getInfo();
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setOrderId(request.getUni());
        storeOrderPram.setUid(currentUser.getUid());
        storeOrderPram.setIsDel(false);
        StoreOrder existStoreOrder = storeOrderService.getInfoByEntity(storeOrderPram);
        if (null == existStoreOrder) {
        	throw new CrmebException("商家已修改订单,请刷新");
        }
        if (existStoreOrder.getPaid()) {
        	throw new CrmebException("该订单已支付");
        }
        //生成子订单
        orderUtils.createPickingOrderInfo(existStoreOrder);
        if (0 != existStoreOrder.getStatus()) {
        	throw new CrmebException("该订单状态不正确! 请刷新后查看订单!");
        }
        // 判断支付类型是否更改
        if(!existStoreOrder.getPayType().equals(request.getPaytype())){
            boolean changePayTypeResult = changePayType(request.getPaytype(), existStoreOrder.getOrderId());
            if(!changePayTypeResult) throw new CrmebException("更新订单支付类型失败");
        }

        // 支付
        if (doPayOrder(request, ip, resultMap, existStoreOrder, false)) return resultMap;
        throw new CrmebException("支付方式错误");
    }

    @Override
    public Object buyMember(BuyMemberRequest request) {
        HashMap<String, Object> resultMap = new HashMap<>();
        CreateOrderResponseVo responseVo;
        try{
            switch (request.getPayType()){
                case Constants.PAY_TYPE_WE_CHAT: //微信支付
                    PayParamsVo payParamsVoRouter = new PayParamsVo(
                            request.getOrderNo(),
                            request.getFromType(),
                            request.getClientIp(),
                            Constants.SERVICE_PAY_TYPE_MEMBER,
                            request.getPrice(),
                            request.getUid(),
                            new AttachVo(Constants.SERVICE_PAY_TYPE_MEMBER, request.getUid())
                    );
                    payParamsVoRouter.setMerId(request.getMerId());
                    responseVo = weChatPayService.create(payParamsVoRouter);//构造下单类
                    responseVo.setMerId(request.getMerId());
                    UserRechargePaymentResponse response = weChatService.response(responseVo);
                    responseVo.setTransJsConfig(response);
                    OrderPayItemResponse itemResponse = new OrderPayItemResponse(responseVo.getPrepayId(), request.getOrderNo());
                    OrderPayResponse orderPayResponse = new OrderPayResponse("WECHAT_PAY",itemResponse);
                    resultMap.put("result", orderPayResponse.getResult());
                    resultMap.put("status","WECHAT_PAY");
                    resultMap.put("jsConfig", responseVo.getTransJsConfig());
                    log.info("--------------- 使用WECHAT_PAY购买会员 ---------------");
                    break;
                case Constants.PAY_TYPE_WE_CHAT_FROM_NATIVE:
                    PayParamsVo payParamsVoRouter1 = new PayParamsVo(
                            request.getOrderNo(),
                            request.getFromType(),
                            request.getClientIp(),
                            Constants.SERVICE_PAY_TYPE_MEMBER,
                            request.getPrice(),
                            request.getUid(),
                            new AttachVo(Constants.SERVICE_PAY_TYPE_MEMBER, request.getUid())
                    );
                    payParamsVoRouter1.setMerId(request.getMerId());
                    responseVo = weChatPayService.create(payParamsVoRouter1);//构造下单类
                    responseVo.setMerId(request.getMerId());
                    UserRechargePaymentResponse response1 = weChatService.response(responseVo);
                    responseVo.setTransJsConfig(response1);
                    OrderPayItemResponse itemResponse1 = new OrderPayItemResponse(responseVo.getPrepayId(), request.getOrderNo());
                    OrderPayResponse orderPayResponse1 = new OrderPayResponse("WECHAT_NATIVE_PAY",itemResponse1);
                    resultMap.put("result", orderPayResponse1.getResult());
                    resultMap.put("status","WECHAT_NATIVE_PAY");
                    resultMap.put("jsConfig", responseVo.getTransJsConfig());
                    log.info("--------------- 使用WECHAT_NATIVE_PAY购买会员 ---------------");
                    break;
                case Constants.PAY_TYPE_YUE:
                    if (userMemberRecordService.yuePayMember(request)){
                        OrderPayResponse orderPayResponseY = new OrderPayResponse("SUCCESS",
                                new OrderPayItemResponse(request.getOrderNo(), request.getOrderNo()));
                        resultMap.put("result", orderPayResponseY.getResult());
                        resultMap.put("status","SUCCESS");
                        log.info("--------------- 使用YUE支付购买会员 ---------------");
                    }
                    break;
            }
        }catch (Exception e){
            logger.error("会员支付失败",e);
            throw new CrmebException("会员支付失败！"+e.getMessage());
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> purchaseProduct(PurchaseProductRequest purchaseProductRequest, String ip) {
        HashMap<String, Object> resultMap = new HashMap<>();
        CreateOrderResponseVo createOrderResponseVo;
        try {
            // 购买产品与服务只扫码，后续有其他方式进行增加，暂时只做扫码方式
            PayParamsVo payParamsVoRouter = new PayParamsVo(
                    purchaseProductRequest.getOrderNo(),
                    "native",
                    ip,
                    Constants.SERVICE_PAY_TYPE_PRODUCT,
                    RoleEnum.getEnumByCode(purchaseProductRequest.getProductType()).getPrice(),
                    null,
                    new AttachVo(Constants.SERVICE_PAY_TYPE_PRODUCT, null)
            );
            payParamsVoRouter.setMerId(productTypeMerchantId);
            createOrderResponseVo = weChatPayService.create(payParamsVoRouter);//构造下单类
            createOrderResponseVo.setMerId(productTypeMerchantId);
            UserRechargePaymentResponse response = weChatService.response(createOrderResponseVo);
            createOrderResponseVo.setTransJsConfig(response);
            OrderPayItemResponse itemResponse = new OrderPayItemResponse(createOrderResponseVo.getPrepayId(), purchaseProductRequest.getOrderNo());
            OrderPayResponse orderPayResponse = new OrderPayResponse("WECHAT_NATIVE_PAY",itemResponse);
            resultMap.put("result", orderPayResponse.getResult());
            resultMap.put("status","WECHAT_NATIVE_PAY");
            resultMap.put("jsConfig", createOrderResponseVo.getTransJsConfig());
            log.info("--------------- 使用WECHAT_NATIVE_PAY购买会员 ---------------");
        } catch (Exception e) {
            log.error("购买产品与服务失败", e);
            throw new CrmebException("购买产品与服务失败！" + e.getMessage());
        }
        return resultMap;
    }

    /**
     * 更换支付类型
     * @param payType 支付类型
     */
    public boolean changePayType(String payType,String orderId) {
        StoreOrder storeOrderPram = new StoreOrder();
        storeOrderPram.setOrderId(orderId);
        StoreOrder existOrder = storeOrderService.getByEntityOne(storeOrderPram);
        if(null == existOrder) throw new CrmebException("未找到订单信息");
        existOrder.setPayType(payType);
        return storeOrderService.updateById(existOrder);
    }

    private void buckleIntegral(StoreOrder storeOrder,StoreOrderInfo storeOrderInfo,String category, String type, String foundsType,Integer reType) {
        try {
            StoreCartResponse response = JSON.parseObject(storeOrderInfo.getInfo(),StoreCartResponse.class);
            StoreProductAttrValue attrInfo = response.getProductInfo().getAttrInfo();
            if(attrInfo.getUseIntegral().compareTo(BigDecimal.ZERO)<1){
                return;
            }
            //更新退款.抵扣的积分要加上
            UserOperateFundsRequest userOperateFundsRequest = new UserOperateFundsRequest();
            userOperateFundsRequest.setUid(storeOrder.getUid());
            userOperateFundsRequest.setValue(attrInfo.getUseIntegral());
            userOperateFundsRequest.setFoundsType(foundsType);
            userOperateFundsRequest.setType(1);
            userOperateFundsRequest.setFoundsCategory(category);
            userOperateFundsRequest.setTitle("退货");
            userOperateFundsRequest.setLinkId(storeOrder.getId().toString());
            //更新佣金/积分
            userService.updateFounds(userOperateFundsRequest, true);
        }catch (Exception e){
            throw new CrmebException("更新退款佣金/积分失败");
        }
    }

    /** 退款积分
     * @param request StoreOrderRefundRequest 退款参数
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    private void subtractBill(StoreOrder storeOrder,StoreOrderRefundRequest request, String category, String type, String foundsType,Integer reType) {
        try{
            FundsMonitorSearchRequest fundsMonitorSearchRequest = new FundsMonitorSearchRequest();
            fundsMonitorSearchRequest.setCategory(category);
            fundsMonitorSearchRequest.setType(type);
            fundsMonitorSearchRequest.setLinkId(request.getOrderId().toString());
            //fundsMonitorSearchRequest.setPm(1);
            PageParamRequest pageParamRequest = new PageParamRequest();
            pageParamRequest.setLimit(Constants.EXPORT_MAX_LIMIT);
            List<UserBill> list = userBillService.getList(fundsMonitorSearchRequest, pageParamRequest);

            if(null == list || list.size() < 1){
                return;
            }

            for (UserBill userBill : list) {
                User user = userService.getById(userBill.getUid());
                if(null == user){
                    continue;
                }


                //更新退款.抵扣的积分要加上
                UserOperateFundsRequest userOperateFundsRequest = new UserOperateFundsRequest();
                userOperateFundsRequest.setUid(user.getUid());
                userOperateFundsRequest.setValue(userBill.getNumber());
                userOperateFundsRequest.setFoundsType(foundsType);
                userOperateFundsRequest.setType(1);
                userOperateFundsRequest.setFoundsCategory(category);
                userOperateFundsRequest.setTitle("退货");
                userOperateFundsRequest.setLinkId("0");

                userService.updateFounds(userOperateFundsRequest, true); //更新佣金/积分
                /*if(category.equals(Constants.USER_BILL_CATEGORY_INTEGRAL)){
                    userBillService.saveRefundIntegralBill(request, user);
                }else{
                    userBillService.saveRefundBrokeragePriceBill(request, user);
                }*/
                //扣减积分对应增加商户余额
                if (reType == 1 && !(userBill.getNumber().compareTo(BigDecimal.ZERO) == 0)) {
                    ChannelMerchantAccount entity = new ChannelMerchantAccount();
                    entity.setMerId(storeOrder.getMerId());
                    entity.setAccount(storeOrder.getDeductionPrice());
                    channelMerchantAccountService.calcMoney(entity);
                    //商户流水记录
                    accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                            AccountFlowTypeEnum.PRODUCT,storeOrder.getDeductionPrice(),null,null,"客户退款时积分返还");
                }
            }
        }catch (Exception e){
            throw new CrmebException("更新退款佣金/积分失败");
        }
    }
}
